<?php
/**
 * lsys task
 * @author     Lonely <shan.liu@msn.com>
 * @copyright  (c) 2017 Lonely <shan.liu@msn.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0
 */
namespace LSYS\Cron;
use LSYS\Cron;

class Dispatcher{
	/**
	 * @var Cron
	 */
	protected $cron;
	/**
	 * 任务派发
	 * @param Cron $cron
	 */
	public function __construct(Cron $cron){
		$this->cron=$cron;
	}
	/**
	 * @var RunJob[]
	 */
	protected $_run_jobs;
	/**
	 * @var int[]
	 */
	protected $_times;
	/**
	 * 初始化变量环境
	 * @return \LSYS\Cron\Dispatcher
	 */
	public function init(){
		$jobs=$this->cron->run_job_list();
		$now_time=time();
		$this->_run_jobs=array();
		$this->_times=array();
		foreach ($jobs as $k=>$v){
			$next_time=$v->get_run_time();
			// 			echo date("Y-m-d H:i:s",$now_time)."\n";
			// 			echo date("Y-m-d H:i:s",$next_time)."\n";
			$offtime=$next_time-$now_time;
			if ($offtime<=0){
				$this->_run_jobs[]=$v;
				if ($v->get_job()->get_skip())$run_time=$now_time;
				else $run_time=$v->get_run_time();
				$next_time=$v->get_job()->get_next_run_time($run_time);
				$this->cron->next_time_job($v->get_job(),$next_time);
				if ($next_time===false)continue;
				$offtime=$next_time-$now_time;
				if ($offtime<=0)$offtime=0;
			}else unset($v);
			// 			echo date("Y-m-d H:i:s",$next_time)."\n";
			// 			echo $offtime."\n";
			$this->_times[]=$offtime;
		}
		// 		print_r($this->_run_jobs);
		unset($jobs);
		return $this;
	}
	/**
	 * 执行任务
	 * @return \LSYS\Cron\Dispatcher
	 */
	public function exec_runer(){
		foreach ($this->_run_jobs as $k=>$v){
			$this->cron->exec_job($v->get_job());
			unset($v,$this->_run_jobs[$k]);
		}
		return $this;
	}
	/**
	 * 执行暂停
	 * @return \LSYS\Cron\Dispatcher
	 */
	public function sleep(){
		if (count($this->_times)==0) $sleep_time=0;
		else{
			$sleep_time=intval(min($this->_times));
			if ($sleep_time==0) return $this;
		}
		$this->cron->on_sleep($sleep_time);
		return $this;
	}
	/**
	 * 后台监听
	 */
	public function listen(){
		while (true){
			$this->init()->exec_runer()->sleep();
		}
	}
}